<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>电子签名板</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet" />
    <script src="https://cdn.jsdelivr.net/npm/vue@3.4.24/dist/vue.global.prod.min.js"></script>
    <style type="text/tailwindcss">
      @layer utilities {
        .content-auto {
          content-visibility: auto;
        }
        .canvas-container {
          @apply bg-white rounded-lg shadow-lg border border-gray-200;
        }
        .btn-primary {
          @apply bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded transition-all duration-200;
        }
        .btn-secondary {
          @apply bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-2 px-4 rounded transition-all duration-200;
        }
        .btn-danger {
          @apply bg-red-500 hover:bg-red-600 text-white font-medium py-2 px-4 rounded transition-all duration-200;
        }
        .btn-outline {
          @apply bg-transparent border border-blue-600 text-blue-600 hover:bg-blue-50 font-medium py-2 px-4 rounded transition-all duration-200;
        }
        .signature-active {
          @apply cursor-crosshair;
        }
      }
    </style>
  </head>
  <body class="bg-gray-50 min-h-screen font-sans">
    <div id="app" class="max-w-6xl mx-auto px-4 py-8">
      <div class="text-center mb-8">
        <h1 class="text-[clamp(1.8rem,4vw,2.5rem)] font-bold text-gray-800 mb-2">电子签名板</h1>
        <p class="text-gray-600">使用鼠标或触摸屏幕进行签名，支持调整画笔粗细和颜色</p>
      </div>

      <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
        <!-- 签名板区域 -->
        <div class="lg:col-span-2">
          <div class="bg-white p-6 rounded-xl shadow-lg">
            <div class="mb-4 flex justify-between items-center">
              <h2 class="text-xl font-semibold text-gray-800">签名区域</h2>
              <div class="flex space-x-2">
                <button id="undoBtn" class="btn-secondary flex items-center" disabled>
                  <i class="fa fa-undo mr-1"></i>
                  撤销
                </button>
                <button id="clearBtn" class="btn-danger flex items-center" disabled>
                  <i class="fa fa-trash mr-1"></i>
                  清空
                </button>
              </div>
            </div>

            <div class="relative">
              <div class="canvas-container relative overflow-hidden" style="height: 400px">
                <canvas id="signatureCanvas" class="w-full h-full"></canvas>

                <!-- 开始签名遮罩 -->
                <div
                  id="startOverlay"
                  class="absolute inset-0 flex flex-col items-center justify-center bg-gray-50/90 rounded-lg transition-opacity duration-300"
                >
                  <p class="text-gray-500 text-lg mb-4">准备签名</p>
                  <button id="startSignBtn" class="btn-primary flex items-center">
                    <i class="fa fa-pencil mr-1"></i>
                    开始签名
                  </button>
                </div>
              </div>
            </div>

            <!-- 控制面板 -->
            <div class="mt-6 flex flex-wrap gap-4 items-center">
              <div class="flex items-center">
                <label for="brushSize" class="text-gray-700 mr-2">画笔粗细:</label>
                <input
                  type="range"
                  id="brushSize"
                  min="1"
                  max="10"
                  value="3"
                  class="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
                  disabled
                />
                <span id="sizeValue" class="ml-2 text-gray-700">3px</span>
              </div>

              <div class="flex items-center">
                <label for="brushColor" class="text-gray-700 mr-2">画笔颜色:</label>
                <input type="color" id="brushColor" value="#000000" class="h-8 w-8 cursor-pointer" disabled />
              </div>

              <button id="saveBtn" class="btn-primary flex items-center" disabled>
                <i class="fa fa-download mr-1"></i>
                保存签名
              </button>
            </div>
          </div>
        </div>

        <!-- 签名信息和预览 -->
        <div class="lg:col-span-1 space-y-6">
          <!-- 签名信息 -->
          <div class="bg-white p-6 rounded-xl shadow-lg">
            <h2 class="text-xl font-semibold text-gray-800 mb-4">签名信息</h2>
            <div class="space-y-4">
              <div>
                <label class="block text-gray-700 text-sm font-medium mb-1">姓名</label>
                <input
                  type="text"
                  id="fullName"
                  placeholder="请输入姓名"
                  class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                />
              </div>

              <div>
                <label class="block text-gray-700 text-sm font-medium mb-1">日期</label>
                <input
                  type="date"
                  id="signDate"
                  class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                />
              </div>

              <div>
                <label class="block text-gray-700 text-sm font-medium mb-1">备注</label>
                <textarea
                  id="remark"
                  rows="3"
                  placeholder="可选"
                  class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                ></textarea>
              </div>

              <button id="applyInfoBtn" class="w-full btn-primary flex items-center justify-center" disabled>
                <i class="fa fa-check mr-1"></i>
                应用信息
              </button>
            </div>
          </div>

          <!-- 签名预览 -->
          <div class="bg-white p-6 rounded-xl shadow-lg">
            <h2 class="text-xl font-semibold text-gray-800 mb-4">签名预览</h2>
            <div class="mb-4">
              <div class="canvas-container h-40 flex items-center justify-center bg-gray-50" id="previewContainer">
                <img id="signaturePreview" src="" alt="签名预览" class="max-w-full max-h-full hidden" />
                <p class="text-gray-400">暂无签名</p>
              </div>
            </div>

            <div class="space-y-3">
              <div class="flex items-center justify-between">
                <span class="text-gray-600">姓名:</span>
                <span id="previewName" class="font-medium">未设置</span>
              </div>
              <div class="flex items-center justify-between">
                <span class="text-gray-600">日期:</span>
                <span id="previewDate" class="font-medium">未设置</span>
              </div>
              <div class="flex items-center justify-between">
                <span class="text-gray-600">尺寸:</span>
                <span id="previewSize" class="font-medium">0x0 px</span>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 底部信息 -->
      <div class="mt-12 text-center text-gray-500 text-sm">
        <p>© 2025 电子签名系统 | 所有签名数据仅用于本地预览</p>
      </div>
    </div>

    <script>
      const { createApp, ref, onMounted, watch } = Vue

      const app = createApp({
        setup() {
          const canvas = ref(null)
          const ctx = ref(null)
          const isDrawing = ref(false)
          const lastX = ref(0)
          const lastY = ref(0)
          const brushSize = ref(3)
          const brushColor = ref('#000000')
          const signatureData = ref(null)
          const hasSignature = ref(false)
          const fullName = ref('')
          const signDate = ref('')
          const remark = ref('')

          // ✅ 新增：存储所有线段数据
          const paths = ref([])

          // ✅ 新增：当前正在绘制的线段
          const currentPath = ref([])

          // 初始化画布
          const initCanvas = () => {
            canvas.value = document.getElementById('signatureCanvas')
            ctx.value = canvas.value.getContext('2d')

            resizeCanvas()

            const today = new Date()
            const formattedDate = today.toISOString().split('T')[0]
            signDate.value = formattedDate
            updatePreviewInfo()
          }

          const resizeCanvas = () => {
            const container = document.getElementById('signatureCanvas')
            const rect = container.getBoundingClientRect()
            const dpr = window.devicePixelRatio || 1

            canvas.value.width = rect.width * dpr
            canvas.value.height = rect.height * dpr
            canvas.value.style.width = `${rect.width}px`
            canvas.value.style.height = `${rect.height}px`

            ctx.value.scale(dpr, dpr)

            ctx.value.clearRect(0, 0, rect.width, rect.height)

            // ✅ 新增：重新绘制历史线段
            redrawAllPaths()
          }

          // ✅ 新增：重新绘制所有线段
          const redrawAllPaths = () => {
            ctx.value.clearRect(0, 0, canvas.value.width, canvas.value.height)

            for (const path of paths.value) {
              ctx.value.beginPath()
              ctx.value.moveTo(path[0].x, path[0].y)
              for (let i = 1; i < path.length; i++) {
                ctx.value.lineTo(path[i].x, path[i].y)
              }
              ctx.value.strokeStyle = brushColor.value
              ctx.value.lineWidth = brushSize.value
              ctx.value.lineCap = 'round'
              ctx.value.stroke()
            }
          }

          // 开始绘制
          const startDraw = e => {
            isDrawing.value = true
            const rect = canvas.value.getBoundingClientRect()
            const x = e.touches ? e.touches[0].clientX - rect.left : e.clientX - rect.left
            const y = e.touches ? e.touches[0].clientY - rect.top : e.clientY - rect.top
            lastX.value = x
            lastY.value = y
            currentPath.value = [{ x, y }]
          }

          // 绘制中
          const draw = e => {
            if (!isDrawing.value) return

            const rect = canvas.value.getBoundingClientRect()
            const x = e.touches ? e.touches[0].clientX - rect.left : e.clientX - rect.left
            const y = e.touches ? e.touches[0].clientY - rect.top : e.clientY - rect.top

            ctx.value.beginPath()
            ctx.value.moveTo(lastX.value, lastY.value)
            ctx.value.lineTo(x, y)
            ctx.value.strokeStyle = brushColor.value
            ctx.value.lineWidth = brushSize.value
            ctx.value.lineCap = 'round'
            ctx.value.stroke()

            lastX.value = x
            lastY.value = y
            currentPath.value.push({ x, y })
          }

          // 结束绘制
          const endDraw = () => {
            if (currentPath.value.length > 1) {
              paths.value.push([...currentPath.value])
            }
            currentPath.value = []
            isDrawing.value = false

            // 更新预览图
            updatePreviewImage()
          }

          // ✅ 新增：撤销上一条线段
          const undoLastLine = () => {
            if (paths.value.length === 0) return
            paths.value.pop()
            redrawAllPaths()
            updatePreviewImage()
          }

          // 清空画布
          const clearCanvas = () => {
            ctx.value.clearRect(0, 0, canvas.value.width, canvas.value.height)
            paths.value = []
            currentPath.value = []
            updatePreviewImage()
            document.getElementById('startOverlay').style.display = 'flex'
          }

          // 更新预览图
          const updatePreviewImage = () => {
            const previewImg = document.getElementById('signaturePreview')
            const noPreviewText = document.getElementById('previewContainer').querySelector('p')

            const dataURL = canvas.value.toDataURL()
            signatureData.value = dataURL
            previewImg.src = dataURL
            previewImg.classList.remove('hidden')
            noPreviewText.style.display = 'none'
          }

          const updatePreviewInfo = () => {
            document.getElementById('previewName').textContent = fullName.value || '未设置'
            document.getElementById('previewDate').textContent = signDate.value || '未设置'
            document.getElementById('previewSize').textContent = `${canvas.value.width}x${canvas.value.height}`
          }

          // 事件监听
          onMounted(() => {
            initCanvas()

            canvas.value.addEventListener('mousedown', startDraw)
            canvas.value.addEventListener('mousemove', draw)
            canvas.value.addEventListener('mouseup', endDraw)
            canvas.value.addEventListener('mouseleave', endDraw)

            canvas.value.addEventListener('touchstart', startDraw)
            canvas.value.addEventListener('touchmove', draw)
            canvas.value.addEventListener('touchend', endDraw)

            // 控件绑定
            document.getElementById('brushSize').addEventListener('input', e => {
              brushSize.value = e.target.value
              document.getElementById('sizeValue').textContent = `${e.target.value}px`
            })

            document.getElementById('brushColor').addEventListener('change', e => {
              brushColor.value = e.target.value
              // ✅ 修改颜色后重绘所有线段
              redrawAllPaths()
            })

            document.getElementById('clearBtn').addEventListener('click', clearCanvas)
            document.getElementById('undoBtn').addEventListener('click', undoLastLine)
            document.getElementById('saveBtn').addEventListener('click', () => {
              const link = document.createElement('a')
              link.download = 'signature.png'
              link.href = canvas.value.toDataURL()
              link.click()
            })

            document.getElementById('applyInfoBtn').addEventListener('click', () => {
              fullName.value = document.getElementById('fullName').value
              signDate.value = document.getElementById('signDate').value
              remark.value = document.getElementById('remark').value
              updatePreviewInfo()
            })

            document.getElementById('startSignBtn').addEventListener('click', () => {
              document.getElementById('startOverlay').style.display = 'none'
              canvas.value.classList.add('signature-active')

              document.getElementById('brushSize').disabled = false
              document.getElementById('brushColor').disabled = false
              document.getElementById('saveBtn').disabled = false
              document.getElementById('applyInfoBtn').disabled = false
              document.getElementById('undoBtn').disabled = false
              document.getElementById('clearBtn').disabled = false
            })
          })

          return {}
        }
      })

      app.mount('#app')
    </script>
  </body>
</html>
